﻿
#include <stdlib.h>
#include <memory.h>

#define LAND_BASE_CORE

#include "init.h"

static struct {
    int exit;
    LandBase config;
    LandCond cond;
    uint32_t wait;
    uint32_t count;
    LandThread threads[256];
    LandThread timerThread;
}ctx = { 0 };

static void
initWorkerContext (LandBase* config){
    ctx.config = *config;
    ctx.count = config->workerCount;
    ctx.wait = 0;
    landInitBaseCond(&ctx.cond);
}

static void
wakupWorker(){
    if(!landTryLockCond(&ctx.cond)){ return; }
    if(ctx.wait >= ctx.count){
        landSignalCond(&ctx.cond);
    }
    landUnlockCond(&ctx.cond);
}

static void *
timerThread (void * arg){
    LandBase config = ctx.config;
    while (!ctx.exit) {
        landDispatchTimer();
        landSleep(config.timerSleep);
        wakupWorker();
    }
    return NULL;
}

static void *
workerThread (void * arg){
    while (!ctx.exit) {
        if(landDispatchWorker() || landDispatchWorker()){
            wakupWorker();
        }else{
            landLockCond(&ctx.cond);
            ctx.wait ++;
            landWaitCond(&ctx.cond);
            ctx.wait--;
            landUnlockCond(&ctx.cond);
        }
    }
    return NULL;
}


LAND_BASE_API void
landDefaultBase (LandBase * conf){
    conf->workerCount = 1;
    conf->timerSleep = 8;
}

LAND_BASE_API int
landInitBase (LandBase * config){
    ctx.exit = 0;
    ctx.config = *config;
    landInitRefContext(config);
    initWorkerContext(config);
    landInitTimerContext();
    landInitServiceContext();
    landInitSocketContext();
    return 0;
}


LAND_BASE_API int
landStartBase (){
    LandBase* config = &ctx.config;
    landNewThread(&ctx.timerThread,
                timerThread, NULL, 1);
    for(uint32_t i = 0; i < ctx.count; i ++){
        landNewThread(&ctx.threads[i],
                workerThread, NULL, 1);
    }
    return 0;
}

LAND_BASE_API int
landExitBase (){
    ctx.exit = 1;
    for (uint32_t i = 0; i < ctx.count; i++) {
        landJoinThread(ctx.threads[i]);
    }
    landExitTimeContext();
    landExitServiceContext();
    landExitSocketContext();
    return 0;
}
